home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CU Amiga Super CD-ROM 21
/
CU Amiga Magazine's Super CD-ROM 21 (1998)(EMAP Images)(GB)[!][issue 1998-04].iso
/
CUCD
/
Programming
/
Python-1.4
/
Source
/
Amiga
/
Python_netlib
/
lineread.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-01-31
|
11KB
|
404 lines
RCS_ID_C="$Id: lineread.c,v 4.2 1994/09/30 00:35:04 jraja Exp $";
/*
* lineread.c - functions to read lines from sockets effectively
*
* Copyright © 1994 AmiTCP/IP Group,
* Network Solutions Development Inc.
* All rights reserved.
*/
/*
* since charRead is a macro package and having no `.c' -file, it's
* documentation is added here
*/
/****** net.lib/charRead ****************************************************
NAME
charRead -- read characters from socket one by one.
SYNOPSIS
initCharRead(rc, fd)
void initCharRead(struct CharRead *, int);
character = charRead(rc)
int charRead(struct CharRead *);
DESCRIPTION
charRead is a macro package which return characters one by one
from given socket input stream. The socket where data is to be read
is set by calling initCharRead(): rc is the pointer to charread
structure previously allocated. fd is the (socket) descriptor where
reading is to be done.
charRead() returns the next character from input stream or one of
the following:
RC_DO_SELECT (-3) - read input buffer is returned. Do select
before next call if you don't want charread
to block.
RC_EOF (-2) - end-of-file condition has occurred.
RC_ERROR (-1) - there has been an error while filling new
charread buffer. Check the value of Errno()
NOTE
Always use variable of type int to store return value from charRead()
since the numeric value of characters returned may vary between
0 -255 (or even greater). As you may know, -3 equals 253 if of type
unsigned char.
EXAMPLE
\*
* This piece of code shows how to use charread with select()
*\
#include <sys/types.h>
#include <sys/socket.h>
#include <charread.h>
main_loop(int sock)
{
struct CharRead rc;
fd_set readfds;
int c;
initCharRead(&rc, sock);
FD_ZERO(&readfds);
while(1) {
FD_SET(sock, &readfds);
if (select(sock + 1. &readfds, NULL, NULL, NULL)) < 0) {
perror("select");
break;
}
if (FD_ISSET(sock, &readfds)) {
while((c = charRead(&rc)) >= 0)
handle_next_input_character(c);
if (c == RC_EOF)
break;
if (c == RC_ERROR) {
perror("charRead");
break;
}
}
}
}
PORTABILITY
The source file charread.h should be able to be used in
UNIX programs as is.
SEE ALSO
lineRead(), bsdsocket.library/recv()
*****************************************************************************
*
*/
/****** net.lib/lineRead *****************************************************
NAME
lineRead -- read newline terminated strings from socket
SYNOPSIS
initLineRead(rl, fd, lftype, bufsize)
void initLineRead(struct LineRead *, int, int, int);
length = lineRead(rl)
int lineread(struct LineRead *);
FUNCTION
lineRead() reads newline terminated strings from given descriptor
very efficiently. All the options needed are set by calling
initLineRead(): rl is the pointer to lineread structure previously
allocated. fd is the (socket) descriptor where reading is to be
done. lftype can have following 3 values:
RL_LFNOTREQ - Newline terminated strings are returned unless
there is no newlines left in currently buffered
input. In this case remaining buffer is returned.
RL_LFREQLF - If there is no newlines left in currently buffered
input the remaining input data is copied at the
start of buffer. Caller is informed that next
call will fill the buffer (and it may block).
Lines are always returned with newline at the end
unless the string is longer than whole buffer.
RL_LFREQNUL - Like LF_REQLF, but remaining newline is removed.
Note here that lenght is one longer that actual
string length since line that has only one
newline at the end would return length as 0
which indigate string incomplete condition.
bufsize is used to tell lineread how big the receive buffer is.
always put RL_BUFSIZE here since that value is used to determine
the memory allocated for the buffer. This option is given to you
so you may decide to use different buffer size than the default
1024.
lineRead() returns the newline terminated string in rl_line field
of lineread structure. Return values of lineRead() are:
1 - RL_BUFSIZE - normal length of returned string.
0 - If zero is returned just after select(),
end-of-file condition has occurred.
Otherwise string is not completed yet.
Make sure you call select() (or use non-
blocking IO) if you don't want next call
to block.
-1 - if rl_Line field of lineread structure
is NULL, it indicates error condition.
If rl_Line points to start of string
buffer, input string has been longer
than buffer. In this case rl_Line points
to zero terminated string of length
RL_BUFSIZE.
You may modify the zero terminated string returned by lineRead() in
any way, but memory around the string is private lineread memory.
EXAMPLE
\*
* The following code shows how to use lineread with select()
*\
#ifdef USE_LOW_MEMORY_BUFFER
#define RL_BUFSIZE 256
#endif
#include <sys/types.h>
#ifdef _AMIGA
#include <bsdsocket.h>
#endif
#include <lineread.h>
#define NULL 0
...
main_loop(int sock)
{
struct LineRead * rl;
int length;
fd_set reafdfs;
if (rl = (struct LineRead *)AllocMem(sizeof (*rl), 0)) {
initLineRead(rl, sock, LF_REQLF, RL_BUFSIZE);
FD_ZERO(&readfds);
while(1) {
FD_SET(sock, &readfds);
if (select(sock + 1, &readfds, NULL, NULL, NULL)) < 0) {
perror("select");
break;
}
if (FD_ISSET(sock, &readfds))
if ((length = lineRead(rl)) == 0) \* EOF *\
break;
do {
if (length > 0)
write(1, rl->rl_Line, length); \* stdout. write() for *\
\* speed demonstration *\
else { \* length == -1 *\
if (rl->rl_Line == NULL); {
perror("lineRead");
break;
}
else {
fprintf(stderr, "lineread input buffer overflow!\n");
write(1, rl->rl_Line, RL_BUFSIZE);
write(1, "\n", 1);
}
}
} while ((length = lineRead(rl)) != 0); \* 0 -> do select() *\
}
FreeMem(rl, sizeof (*rl);
}
else
fprintf("AllocMem: Out Of memory\n");
}
PORTABILITY
The source modules lineread.c and lineread.h should compile
in UNIX machines as is.
SEE ALSO
charRead(), bsdsocket.library/recv()
******************************************************************************
*/
#include "lineread.h"
#ifdef _AMIGA
extern struct Library * SocketBase;
#define READ(a, b, c) recv(a, b, c, 0)
#if __SASC
#include <proto/socket.h>
#elif __GNUC__
#include <inline/socket.h>
#endif
#else /* not _AMIGA */
#define READ(a, b, c) read(a, b, c)
#endif /* _AMIGA */
#ifndef NULL
#define NULL 0
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef __CONCAT
#if defined (__STDC__) || defined (__cplusplus)
#define __CONCAT(x,y) x ## y
#else
#define __CONCAT(x,y) x/**/y
#endif
#endif /* __CONCAT not defined */
#define RLP(field) __CONCAT(rl->rl_Private.rlp_,field)
#if defined (__STDC__) || defined (__cplusplus)
int lineRead(struct LineRead * rl)
#else
int lineRead(rl)
struct LineRead * rl;
#endif
{
int i;
if (RLP(Bufpointer) == RLP(Howlong))
if (RLP(Selected)) {
if (RLP(Line_completed))
RLP(Startp) = RLP(Bufpointer) = 0;
if ((i = READ(rl->rl_Fd,
RLP(Buffer) + RLP(Bufpointer),
RLP(Buffersize) - RLP(Bufpointer))) <= 0) {
/*
* here if end-of-file or on error. set Howlong == Bufpointer
* so if non-blocking I/O is in use next call will go to READ()
*/
RLP(Howlong) = RLP(Bufpointer);
rl->rl_Line = NULL;
return i;
}
else
RLP(Howlong) = RLP(Bufpointer) + i;
}
else /* Inform user that next call may block (unless select()ed) */
{
RLP(Selected) = TRUE;
return 0;
}
else /* Bufpointer has not reached Howlong yet. */
{
RLP(Buffer)[RLP(Bufpointer)] = RLP(Saved);
RLP(Startp) = RLP(Bufpointer);
}
/*
* Scan read string for next newline.
*/
while (RLP(Bufpointer) < RLP(Howlong))
if (RLP(Buffer)[RLP(Bufpointer)++] == '\n')
goto Skip;
/*
* Here if Bufpointer == Howlong.
*/
if (rl->rl_Lftype != RL_LFNOTREQ) {
RLP(Selected) = TRUE;
if (RLP(Bufpointer) == RLP(Buffersize)) {
/*
* Here if Bufpointer reaches end-of-buffer.
*/
if (RLP(Startp) == 0) { /* (buffer too short for whole string) */
RLP(Line_completed) = TRUE;
rl->rl_Line = RLP(Buffer);
RLP(Buffer)[RLP(Bufpointer)] = '\0';
return -1;
}
/*
* Copy partial string to start-of-buffer and make control ready for
* filling rest of buffer when next call to lineRead() is made
* (perhaps after select()).
*/
for (i = 0; i < RLP(Buffersize) - RLP(Startp); i++)
RLP(Buffer)[i] = RLP(Buffer)[RLP(Startp) + i];
RLP(Howlong)-= RLP(Startp);
RLP(Bufpointer) = RLP(Howlong);
RLP(Startp) = 0;
}
RLP(Line_completed) = FALSE;
return 0;
}
Skip:
RLP(Line_completed) = TRUE;
if (rl->rl_Lftype == RL_LFREQNUL)
RLP(Buffer)[RLP(Bufpointer) - 1] = '\0';
RLP(Saved) = RLP(Buffer)[RLP(Bufpointer)];
RLP(Buffer)[RLP(Bufpointer)] = '\0';
RLP(Selected) = FALSE;
rl->rl_Line = RLP(Buffer) + RLP(Startp);
return (RLP(Bufpointer) - RLP(Startp));
}
#undef READ
#if defined (__STDC__) || defined (__cplusplus)
void initLineRead(struct LineRead * rl, int fd, int lftype, int buffersize)
#else
int initLineRead(rl, fd, lftype, buffersize)
struct LineRead * rl;
int fd;
int lftype;
int buffersize;
#endif
{
rl->rl_Fd = fd;
rl->rl_Lftype = lftype;
RLP(Bufpointer) = RLP(Howlong) = 0;
RLP(Selected) = RLP(Line_completed) = TRUE;
RLP(Buffersize) = buffersize;
}